/*
 * Copyright (C) 2006 Johan Maasing johan at zoom.nu Licensed under the Apache
 * License, Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
 * or agreed to in writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package nu.zoom.catonine.swing.rule;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;

import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import nu.zoom.catonine.fontchooser.FontChooserFactory;
import nu.zoom.catonine.stylerule.StyleRule;
import nu.zoom.catonine.stylerule.StyleRules;
import nu.zoom.gal.error.ErrorReporter;
import nu.zoom.swing.action.AbstractTypedAction;
import nu.zoom.swing.desktop.Workbench;
import nu.zoom.swing.layout.VerticalPanel;
import nu.zoom.ui.Resources;
import nu.zoom.ui.Resources.ResourceNotFoundException;

/**
 * A panel to display a table of style rules and actions to arrange the order of
 * the style rules.
 * 
 * @author "Johan Maasing" &lt;johan@zoom.nu&gt;
 * 
 */
public class ConfigPanel extends JPanel implements ListSelectionListener {

	private static final long serialVersionUID = 1L;
	private ConfigTableModel configTableModel;
	private JTable configTable;
	private JButton addStyleRuleButton;
	private JButton deleteStyleRuleButton;
	private JButton moveUpButton;
	private JButton moveDownButton;
	private StyleRules styleRules;
	private StyleRuleEditPanel editPanel;

	public ConfigPanel(final Workbench workbench,
			final FontChooserFactory fontChooserFactory,
			final Resources messages, final ErrorReporter errorReporter,
			final StyleRules styleRules, final Font defaultFont)
			throws ResourceNotFoundException {
		super(new BorderLayout());
		this.styleRules = styleRules;

		StyleRulesDataEditPanel dataPanel = new StyleRulesDataEditPanel(
				messages, styleRules);

		MoveUpAction moveUpAction = new MoveUpAction(messages);
		MoveDownAction moveDownAction = new MoveDownAction(messages);
		AddAction addAction = new AddAction(messages);
		DeleteAction deleteAction = new DeleteAction(messages);
		moveUpButton = new JButton(moveUpAction);
		moveDownButton = new JButton(moveDownAction);
		addStyleRuleButton = new JButton(addAction);
		deleteStyleRuleButton = new JButton(deleteAction);

		configTableModel = new ConfigTableModel(messages, styleRules);
		configTable = new JTable(configTableModel);
		int preferredHeight = configTable.getRowHeight() * 8;
		configTable.setPreferredScrollableViewportSize(new Dimension(
				configTable.getPreferredScrollableViewportSize().width,
				preferredHeight));
		configTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		configTable.setCellSelectionEnabled(false);
		configTable.setRowSelectionAllowed(true);
		configTable.setShowVerticalLines(false);
		configTable.getSelectionModel().addListSelectionListener(this);
		configTable.getColumnModel().getColumn(1)
				.setCellRenderer(new StyleRuleColorCellRenderer());
		JScrollPane tableScroller = new JScrollPane(configTable);

		editPanel = new StyleRuleEditPanel(workbench, fontChooserFactory,
				messages, errorReporter, defaultFont);

		JPanel movePanel = new JPanel(new FlowLayout());
		movePanel.add(moveUpButton);
		movePanel.add(moveDownButton);

		JPanel addDeletePanel = new JPanel(new FlowLayout());
		addDeletePanel.add(addStyleRuleButton);
		addDeletePanel.add(deleteStyleRuleButton);

		VerticalPanel mainPanel = new VerticalPanel();
		mainPanel.addRow(dataPanel);
		mainPanel.addRow(tableScroller);
		mainPanel.addRow(movePanel);
		mainPanel.addRow(addDeletePanel);
		mainPanel.addRow(editPanel);

		add(mainPanel, BorderLayout.NORTH);
		editPanel.unsetStyleRule();
		moveUpButton.setEnabled(false);
		moveDownButton.setEnabled(false);
		deleteStyleRuleButton.setEnabled(false);
	}

	@Override
	public void valueChanged(ListSelectionEvent e) {
		// Ignore extra messages.
		if (e.getValueIsAdjusting()) {
			return;
		}

		int selectedRow = configTable.getSelectedRow();
		if ((selectedRow > -1) && (selectedRow < configTable.getRowCount())) {
			StyleRule styleRule = configTableModel.getValueAt(selectedRow);
			editPanel.setStyleRule(styleRule);
			moveUpButton.setEnabled((selectedRow > 0));
			moveDownButton.setEnabled((selectedRow < (configTableModel
					.getRowCount() - 1)));
			deleteStyleRuleButton.setEnabled(true);
		} else {
			editPanel.unsetStyleRule();
			moveUpButton.setEnabled(false);
			moveDownButton.setEnabled(false);
			deleteStyleRuleButton.setEnabled(false);
		}
	}

	class MoveUpAction extends AbstractTypedAction {

		private static final long serialVersionUID = 1L;

		public MoveUpAction(Resources messages)
				throws ResourceNotFoundException {
			super();
			setName(messages.getMessage("nu.zoom.catonine.stylerule.up"));
			setToolTip(messages.getMessage("nu.zoom.catonine.stylerule.up.tt"));
			setIcon(messages.getIcon("nu.zoom.catonine.stylerule.up.icon"));
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			editPanel.unsetStyleRule();
			int selectedRow = configTable.getSelectedRow();
			if (selectedRow != -1) {
				StyleRule rule = configTableModel.getValueAt(selectedRow);
				styleRules.moveUp(rule);
				int index = styleRules.getPatternStyles().indexOf(rule);
				configTable.clearSelection();
				configTable.setRowSelectionInterval(index, index);
			}
		}
	}

	class MoveDownAction extends AbstractTypedAction {

		private static final long serialVersionUID = 1L;

		public MoveDownAction(Resources messages)
				throws ResourceNotFoundException {
			super();
			setName(messages.getMessage("nu.zoom.catonine.stylerule.down"));
			setToolTip(messages
					.getMessage("nu.zoom.catonine.stylerule.down.tt"));
			setIcon(messages.getIcon("nu.zoom.catonine.stylerule.down.icon"));
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			editPanel.unsetStyleRule();
			int selectedRow = configTable.getSelectedRow();
			if (selectedRow != -1) {
				StyleRule rule = configTableModel.getValueAt(selectedRow);
				styleRules.moveDown(rule);
				int index = styleRules.getPatternStyles().indexOf(rule);
				configTable.clearSelection();
				configTable.setRowSelectionInterval(index, index);
			}
		}
	}

	class DeleteAction extends AbstractTypedAction {

		private static final long serialVersionUID = 1L;

		public DeleteAction(Resources messages)
				throws ResourceNotFoundException {
			super();
			setName(messages.getMessage("nu.zoom.catonine.stylerule.delete"));
			setToolTip(messages
					.getMessage("nu.zoom.catonine.stylerule.delete.tt"));
			setIcon(messages.getIcon("nu.zoom.catonine.stylerule.delete.icon"));
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			editPanel.unsetStyleRule();
			int selectedRow = configTable.getSelectedRow();
			if (selectedRow != -1) {
				StyleRule rule = configTableModel.getValueAt(selectedRow);
				styleRules.remove(rule);
			}
		}
	}

	class AddAction extends AbstractTypedAction {

		private static final long serialVersionUID = 1L;

		public AddAction(Resources messages) throws ResourceNotFoundException {
			super();
			setName(messages.getMessage("nu.zoom.catonine.stylerule.add"));
			setToolTip(messages.getMessage("nu.zoom.catonine.stylerule.add.tt"));
			setIcon(messages.getIcon("nu.zoom.catonine.stylerule.add.icon"));
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			StyleRule newRule = new StyleRule();
			newRule.setPattern(".*");
			styleRules.add(newRule);
			setActiveRule(newRule);
		}
	}

	public void setActiveRule(StyleRule rule) {
		if (rule != null) {
			editPanel.unsetStyleRule();
			configTable.clearSelection();
			final int index = styleRules.getPatternStyles().indexOf(rule);
			if (index >= 0) {
				configTable.setRowSelectionInterval(index, index);
			}
		}
	}
}
